<?php
//$Id: db.php 180 2012-02-26 06:32:20Z tomqin@gmail.com $

/**
 * DB 数据操作类
 *
 * @copyright		Copyright (C) 2010-2012 SupeFun.com Inc.
 * @author			TomQin <tomqin@gmail.com>
 * @license			http://www.supefun.com/license/
 * @package Core
 */


final class DB {

	/**
	 * The established database connections.
	 *
	 * @var array
	 */
	public static $connects = array();

	public static $current = '';

	/**
	 * Get a database connection.
	 *
	 * If no database name is specified, the default connection will be returned.
	 *
	 * <code>
	 *		// Get the default database connection for the application
	 *		$key = DB::connection();
	 *
	 *		// Get a specific connection by passing the connection name
	 *		$key = DB::connection('database.mysql');
	 * </code>
	 *
	 * @param  string	  $key
	 * @return Connection
	 */
	public static function connection($key = '')
	{
		if (empty($key))
			$key = self::getCurrent();

		if (!isset(self::$connects[$key]))
		{
			$config = Config::get($key);

			if (is_null($config)) {
				throw new Exception("Connection is not defined for [$key].");
			}

			self::setCurrent($key);
			self::$connects[$key] = new DB_MySQL($config);
		}

		return self::$connects[$key];
	}

	static function getCurrent()
	{
		if(self::$current)
			return self::$current;
		else
			return 'database.default';
		return $t;
	}

	static function setCurrent($var)
	{
		self::$current = $var;
	}

	public static function exec()
	{
		$args = func_get_args();
		return self::__callStatic('exec', $args);
	}

	public static function query()
	{
		$args = func_get_args();
		return self::__callStatic('query', $args);
	}

	public static function prepare()
	{
		$args = func_get_args();
		return self::__callStatic('prepare', $args);
	}

	public static function escape($string)
	{
		return trim(self::quote($string), "'");
	}

	public static function quote()
	{
		$args = func_get_args();
		return self::__callStatic('quote', $args);
	}

	public static function lastInsertId()
	{
		$args = func_get_args();
		return self::__callStatic('lastInsertId', $args);
	}

	public static function setAttribute()
	{
		$args = func_get_args();
		return self::__callStatic('setAttribute', $args);
	}

	public static function __callStatic($method, $args)
	{
		return call_user_func_array(array(self::connection(), $method), $args);
	}

	public static function getAll($sql, $bind = array(), $key = '')
	{
		if($bind){
			$stmt = self::prepare($sql);
			$stmt->execute($bind);
			$data = $stmt->fetchAll();
		}else{
			$data = self::query($sql)->fetchAll();
		}
		if($key){
			foreach($data as $item){
				$row[$item[$key]] = $item;
			}
			$data = $row;
		}
		return $data;
	}

	public static function getFirst($sql, $bind = array())
	{
		$stmt = self::prepare($sql);
		$stmt->execute($bind);
		return $stmt->fetchColumn();
	}

	public static function getOne($sql, $bind = array())
	{
		$stmt = self::prepare($sql);
		$stmt->execute($bind);
		return $stmt->fetch();
	}

	public static function getSql($field, $table, $where, $limit = '', $order = '', $group = '')
	{
		$where = empty($where) ? '' : ' WHERE '.self::where($where);
		$order = empty($order) ? '' : ' ORDER BY '.$order;
		$group = empty($group) ? '' : ' GROUP BY '.$group;
		$limit = empty($limit) ? '' : ' LIMIT '.$limit;

		return 'SELECT '.$field.' FROM '.$table.$where.$group.$order.$limit;
	}

	public static function where($where)
	{
		if(is_array($where)){
			$sql = $comm = '';
			foreach($where as $k => $v){
				$sql .= $comm . "`$k` = " . (is_null($v) ? "NULL" : DB::quote($v));
				$comm = ' AND ';
			}
			return $sql;
		}else{
			return $where;
		}
	}

	public static function insert($table, $data, $replace = false)
	{
		if(!is_array($data) || count($data) == 0 || $table == '') {
			return false;
		}

		$fields = current($data);
		if(!is_array($fields)){
			$fields = $data;
			$data   = array(0 => $data);
		}

		$cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';
		$sql = $cmd.' `'.$table.'` SET';
		$comm = '';
		foreach($fields as $key => $var){
			$sql .= $comm." `{$key}` = :{$key}";
			$comm = ',';
		}

		$stmt = DB::prepare($sql);
		foreach($data as $line){
			foreach($line as $k=>$v){
				$stmt->bindValue(":{$k}", $v);
			}
			$stmt->execute();
			$res[] = DB::lastInsertId();
		}
	}

	public static function update($table, $data, $where = '') {
		if($table == '') {
			return false;
		}

		$where = empty($where) ? '' : ' WHERE '.self::where($where);
		$field = '';
		if (is_array($data) && count($data) > 0) {
			$fields = array();
			foreach($data as $k=>$v) {
				switch (substr($v, 0, 2)) {
					case '+=':
					case '-=':
					case '/=':
					case '*=':
						$t = substr($v, 0, 1); // +、-、*、/
						$n = substr($v, 2);
						if (is_numeric($n)) {
							$fields[] = $k .'='. $k .$t. $n;
						} else {
							continue;
						}
						break;
					default:
						$fields[] = $k .'='. self::quote($v);
				}
			}
			$field = implode(',', $fields);
		} else {
			return false;
		}

		$sql = 'UPDATE '.$table.' SET '.$field.$where;
		return self::exec($sql);
	}
}


final class DB_MySQL extends Pdo{

	/**
	 * Establish a PDO database connection for a given database configuration.
	 *
	 * @param array
	 * @return PDO
	 */
	public function __construct($config)
	{
		$host	 = isset($config['host']) ? $config['host'] : 'localhost';
		$port	 = isset($config['port']) ? $config['port'] : '3066';
		$database = isset($config['database']) ? $config['database'] : '';
		$username = isset($config['username']) ? $config['username'] : '';
		$password = isset($config['password']) ? $config['password'] : '';
		$charset  = isset($config['charset']) ? $config['charset'] : '';
		$options  = isset($config['options']) ? $config['options'] : array();

		$dsn = sprintf('mysql:host=%s;dbname=%s;port=%d', $host, $database, $port);

		try{
			parent::__construct($dsn, $username, $password);
		}catch(PDOException $e){
			header("HTTP/1.1 500 Internal Server Error");
			exit($e->getMessage());
		}
		$this->initAttributes();

		//默认字符集
		if ($charset) {
			$this->prepare("SET NAMES {$charset}")->execute();
		}
	}

	/**
	 * connection options for the PDO object.
	 *
	 * @return void
	 */
	protected function initAttributes()
	{
		$this->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
		$this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);	//默认 FetchMode
		$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);			//错误模式
	}
}
?>
